#include <stdio.h>
#include <stdlib.h>
#include <smp.h>
#include <cpu.h>
#include <spinlock.h>
#include <errno.h>

typedef struct {
    void *arg;
    bool wait;
    cpu_synctoken_t wait_for_completion;
} call_data_t;

static void smp_handler(uintptr_t event, uintptr_t data)
{
    smp_call_func_t fn = (smp_call_func_t)event;
    call_data_t *cdata = (call_data_t *)data;

    fn(cdata->arg);

    if (cdata->wait)
        cpu_sync_barrier(&cdata->wait_for_completion);

    free(cdata);
}
DECLARE_CPU_MSG_HANDLER(smp_handler, SMP_HANDLE_ID);

/*
 * smp_call_function - 在指定的@target_cpu上执行函数@func
 * @func: 要执行的函数指针
 * @arg: 传递给函数的参数
 * @wait: 为真时表示需要等待@func执行完毕后,本函数才能返回
 * Return: 0 on success, else a negative status code
 */
int smp_call_function(int target_cpu, smp_call_func_t func, void *arg, bool wait)
{
    cpu_msg_t msg;
    call_data_t *cdata = NULL;
    bool is_self;

    is_self = (target_cpu == get_cpuid());
    if (is_self)
        wait = false;

    cdata = malloc(sizeof(call_data_t));
    if (!cdata)
        return -ENOMEM;

    cdata->arg = arg;
    cdata->wait = wait;
    if (wait)
        cpu_sync_init(&cdata->wait_for_completion, 2);

    msg.handler = SMP_HANDLE_ID,
    msg.event = (uintptr_t)func,
    msg.data = (uintptr_t)cdata;

    cpu_send_msg(target_cpu, &msg);

    if (wait)
        cpu_sync_barrier(&cdata->wait_for_completion);

    return 0;
}
